/*
    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#include "ray.h"
*/

#include "cgpanel/raytracer/box.h"
#include "cgpanel/raytracer/ray.h"
#include "objects/vertex.h"

#include <iostream>
#include <algorithm>
using namespace std;

namespace draw
{
Box* Box::combine(Box *temp)
{
  float xmin = m_xmin;
  xmin = min(xmin, temp->getXmin());
  
  float ymin = m_ymin;
  ymin = min(ymin, temp->getYmin());
  
  float zmin = m_zmin;
  zmin = min(zmin, temp->getZmin());
  
  float xmax = m_xmax;
  xmax = max(xmax, temp->getXmax());
  
  float ymax = m_ymax;
  ymax = max(ymax, temp->getYmax());
  
  float zmax = m_zmax;
  zmax = max(zmax, temp->getZmax());
  
  Box * newBox = new Box();
  newBox->setValues(xmin, ymin, zmin, xmax, ymax, zmax);
  
  return newBox;
}

void Box::prepare(object::Vertex * valOrigin)
{
  xminREC = m_xmin - valOrigin->x();
  xmaxREC = m_xmax - valOrigin->x();
  yminREC = m_ymin - valOrigin->y();
  ymaxREC = m_ymax - valOrigin->y();
  zminREC = m_zmin - valOrigin->z();
  zmaxREC = m_zmax - valOrigin->z();
}

bool Box::hit(draw::Ray * ray, bool dummy)
{
  reciproc = ray->getInvX();

  if(reciproc >= 0){
    txmin = reciproc*xminREC;
    txmax = reciproc*xmaxREC;
  }else{
    txmin = reciproc*xmaxREC;
    txmax = reciproc*xminREC;
  }

  reciproc = ray->getInvY();
  if(reciproc >= 0){
    tymin = reciproc*yminREC;
    tymax = reciproc*ymaxREC;
  }else{
    tymin = reciproc*ymaxREC;
    tymax = reciproc*yminREC;
  }
  
  if( txmin > tymax || tymin > txmax)
    return false;

  reciproc = ray->getInvZ();
  if(reciproc >= 0){
    tzmin = reciproc*zminREC;
    tzmax = reciproc*zmaxREC;
  }else{
    tzmin = reciproc*zmaxREC;
    tzmax = reciproc*zminREC;
  }
  
  //TODO is correct???
  if(   txmin > tzmax || tymin > tzmax ||
        tzmin > txmax || tzmin > tymax)
  {
    return false;
  }
  
    return true;
  
  
}

bool Box::hit(draw::Ray * ray)
{
  reciproc = ray->getInvX();
  xminREC = reciproc*(m_xmin - ray->origin()->x());
  xmaxREC = reciproc*(m_xmax - ray->origin()->x());
  txmin = reciproc >= 0 ? xminREC:xmaxREC;
  txmax = reciproc >=0  ? xmaxREC:xminREC;

  reciproc = ray->getInvY();
  yminREC = reciproc*(m_ymin - ray->origin()->y());
  ymaxREC = reciproc*(m_ymax - ray->origin()->y());
  tymin = reciproc >= 0 ? yminREC:ymaxREC;
  tymax = reciproc >=0 ? ymaxREC:yminREC;
  
  if( txmin > tymax || tymin > txmax)
    return false;

  reciproc = ray->getInvZ();
  zminREC = reciproc*(m_zmin - ray->origin()->z());
  zmaxREC = reciproc*(m_zmax - ray->origin()->z());
  tzmin = reciproc >= 0 ? zminREC:zmaxREC;
  tzmax = reciproc >= 0 ? zmaxREC:zminREC;

  if(   txmin > tzmax || tymin > tzmax ||
        tzmin > txmax || tzmin > tymax)
  {
    return false;
  }
  else{
    return true;
  }
}
  
}

